import cv2
import numpy as np
import time

def angle_cos(p0, p1, p2):
    d1, d2 = (p0 - p1).astype('float'), (p2 - p1).astype('float')
    return abs(np.dot(d1, d2) / np.sqrt(np.dot(d1, d1) * np.dot(d2, d2)))

def get_rectangle(img1_bin):  # 输入二值化的图片，返回最外层矩形的四个角点坐标，且排序为逆时针
    contours, _hierarchy = cv2.findContours(img1_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    index = 0
    squares = []
    for cnt in contours:
        cnt_len = cv2.arcLength(cnt, True)  # 计算轮廓周长
        if cnt_len < 500:
            continue
        cnt = cv2.approxPolyDP(cnt, 0.08 * cnt_len, True)  # 多边形逼近
        # 条件判断逼近边的数量是否为4，轮廓面积是否大于1000，检测轮廓是否为凸的
        if len(cnt) == 4 and cv2.contourArea(cnt) > 200 and cv2.isContourConvex(cnt):
            cnt = cnt.reshape(-1, 2)
            max_cos = np.max([angle_cos(cnt[i], cnt[(i + 1) % 4], cnt[(i + 2) % 4]) for i in range(4)])
            # 只检测矩形（cos90° = 0）
            if max_cos < 0.2:
                # 检测四边形（不限定角度范围）
                # if True:
                index = index + 1
                # cv2.putText(img1_filterred, ("#%d" % index), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 255), 2)
                squares.append(cnt)

    index_left_up = np.argmin(np.sum(squares[0] * np.array([1, 1]), axis=1))
    index_left_down = np.argmin(np.sum(squares[0] * np.array([1, -1]), axis=1))
    index_right_down = np.argmax(np.sum(squares[0] * np.array([1, 1]), axis=1))
    index_right_up = np.argmax(np.sum(squares[0] * np.array([1, -1]), axis=1))

    x1, y1 = squares[0][index_left_up]  # x,y坐标形式，排序为从左上方点开始，逆时针的顺序
    x2, y2 = squares[0][index_left_down]
    x3, y3 = squares[0][index_right_down]
    x4, y4 = squares[0][index_right_up]

    return x1, y1, x2, y2, x3, y3, x4, y4

class my_timer():
    def __init__(self):
        self.ts = 0  # 自己的坐标

    def tic(self):
        self.ts = time.perf_counter()

    def toc(self):
        print("time used:"+str(time.perf_counter()-self.ts))